/**
 * @file      ac_tlm_mul.h
 * @author    Luisa Madeira Cardoso
 *
 */

//////////////////////////////////////////////////////////////////////////////

#ifndef MUL_H_
#define MUL_H_

//////////////////////////////////////////////////////////////////////////////

// Standard includes
// SystemC includes
#include <systemc>
// ArchC includes
#include "ac_tlm_protocol.H"

//////////////////////////////////////////////////////////////////////////////

// using statements
using tlm::tlm_transport_if;

//////////////////////////////////////////////////////////////////////////////

//#define DEBUG

/// Namespace to isolate memory from ArchC
namespace user
{

/// A TLM memory
class ac_tlm_mul :
  public sc_module,
  public ac_tlm_transport_if // Using ArchC TLM protocol
{
public:
  /// Exposed port with ArchC interface
  sc_export< ac_tlm_transport_if > target_export;
  /// Internal write
  ac_tlm_rsp_status writel( const uint32_t & , const uint32_t & );
  /// Internal read
  ac_tlm_rsp_status readl( const uint32_t & , uint32_t & );
  void mul();


  /**
   * Implementation of TLM transport method that
   * handle packets of the protocol doing apropriate actions.
   * This method must be implemented (required by SystemC TLM).
   * @param request is a received request packet
   * @return A response packet to be send
  */
  ac_tlm_rsp transport( const ac_tlm_req &request ) {

    ac_tlm_rsp response;

    switch( request.type ) {
    case READ :     // Packet is a READ one
      response.status = readl(request.addr, response.data); 
      //  if(request.addr == 5242884) {
      //   printf("read p1 %d\n", response.data );
      // }
      // else if(request.addr == 5242888) {
      //   printf("read p2 %d\n", response.data );
      // }
      // else if(request.addr > 5242880 && request.addr < 5242888) {
      //   printf("read meio %d\n", response.data );
      // }
      //printf("READ addr: %d data: %d\n",request.addr, response.data );
      break;
    case WRITE:     // Packet is a WRITE
      //printf("WRITE addr: %d data: %d\n",request.addr, request.data );
      // if(request.addr == 5242884) {
      //     printf("p1 %d\n", request.data );
      //   }
      //   else if(request.addr == 5242888) {
      //     printf("p2 %d\n", request.data );
      //   }
      //   else if(request.addr > 5242880 && request.addr < 5242888) {
      //     printf("meio %d\n", request.data );
      //   }
        response.status = writel(request.addr, request.data); 
      break;
    default :
      response.status = ERROR;
      break;
    }

    return response;
  }


  /**
   * Default constructor.
   *
   * @param k Memory size in kilowords.
   *
   */
  ac_tlm_mul( sc_module_name module_name );

  /**
   * Default destructor.
   */
  ~ac_tlm_mul();

private:
  uint8_t *mul_mem;
  union word_t {
    double b;
    int i[2];
    char c[8];
  } ;
  word_t result;
  word_t p1;
  word_t p2;

};

};

#endif //MUL_H_
